/*
 * CItem.java
 *
 * Copyright (c) 2009 Giles Millward (Manigra). All rights reserved.
 *
 * This file is part of JRogueDPS.
 *
 * JRogueDPS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JRogueDPS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with JRogueDPS.  If not, see <http://www.gnu.org/licenses/>.
 */

package geardatabase;

import geardatabase.CGemType.GemType;
import geardatabase.CItemQuality.ItemQuality;
import geardatabase.CItemSlot.ItemSlot;
import geardatabase.CItemType.ItemType;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Element;
import org.dom4j.Node;
import utility.CUtility;

/**
 *
 * @author gmillward
 */
public class CItem {

    private int m_id;
    private String m_name = null;
    private ItemQuality m_itemQuality = null;
    private ItemType m_itemType = null;
    private ItemSlot m_itemSlot = null;
    private GemType m_gemType = null;
    private int m_iLevel;
    private String m_htmlTooltip = null;
    private ArrayList<CSocketHolder> m_socketHolderList = new ArrayList<CSocketHolder>();
    private CStats m_itemStats = new CStats();
    private CStats m_itemBonusStats = new CStats();
    private double m_weaponSpeed = 0.0;
    private double m_maxWeaponDamage = 0;
    private double m_minWeaponDamage = 0;
    private boolean m_modified = false;

    CItem(int p_id)
    {
        m_id = p_id;
    }

    CItem(int p_id, String p_itemName, ItemSlot p_itemSlot, ItemType p_itemType, CStats p_itemStats)
    {
        m_id = p_id;
        m_name = p_itemName;
        m_itemQuality = ItemQuality.COMMON;
        m_itemType = p_itemType;
        m_itemSlot = p_itemSlot;
        m_gemType = null;
        m_iLevel = 0;
        m_htmlTooltip = "";
        m_itemStats = p_itemStats;
    }
    
    CItem(Element p_xmlElement)
    {
        parseXMLElement(p_xmlElement);
    }

    public void showData()
    {
        System.out.println("m_id " + m_id + " m_name " + m_name + 
                           " m_gearQuality " + getGearQuality(m_itemQuality) + "\n" + "iLevel " + m_iLevel +
                           "\n" + "m_htmlTooltip " + m_htmlTooltip + "\n" +
                           "ItemType: " + m_itemType + " ItemSlot:" + m_itemSlot);
        System.out.println("m_weaponSpeed:" + m_weaponSpeed + " minDmg:" + m_minWeaponDamage + " maxDmg:" + m_maxWeaponDamage);
        for (int i = 0;i < m_socketHolderList.size(); i++)
        {
            System.out.println("Socket " + i + " = " + CGemType.getGemName(m_socketHolderList.get(i).getSocketType()));
        }

        m_itemStats.showData();
        m_itemBonusStats.showData();
    }

    public String getNonZeroStatsString()
    {
        String l_string = "";
        if (m_itemStats.m_strength != 0 || m_itemBonusStats.m_strength != 0)
        {
            l_string += " Str +" + (m_itemStats.m_strength + m_itemBonusStats.m_strength);
        }

        if (m_itemStats.m_attackPower != 0 || m_itemBonusStats.m_attackPower != 0)
        {
            l_string += " Atk +" + (m_itemStats.m_attackPower + m_itemBonusStats.m_attackPower);
        }

        if (m_itemStats.m_agility != 0 || m_itemBonusStats.m_agility != 0)
        {
            l_string += " Agi +" + (m_itemStats.m_agility + m_itemBonusStats.m_agility);
        }

        if (m_itemStats.m_stamina != 0 || m_itemBonusStats.m_stamina != 0)
        {
            l_string += " Sta +" + (m_itemStats.m_stamina + m_itemBonusStats.m_stamina);
        }

        if (m_itemStats.m_hitRating != 0 || m_itemBonusStats.m_hitRating != 0)
        {
            l_string += " Hit +" + (m_itemStats.m_hitRating + m_itemBonusStats.m_hitRating);
        }

        if (m_itemStats.m_critRating != 0 || m_itemBonusStats.m_critRating != 0)
        {
            l_string += " Crit +" + (m_itemStats.m_critRating + m_itemBonusStats.m_critRating);
        }

        if (m_itemStats.m_expertiseRating != 0 || m_itemBonusStats.m_expertiseRating != 0)
        {
            l_string += " Exp +" + (m_itemStats.m_expertiseRating + m_itemBonusStats.m_expertiseRating);
        }

        if (m_itemStats.m_armorPenRating != 0 || m_itemBonusStats.m_armorPenRating != 0)
        {
            l_string += " ArP +" + (m_itemStats.m_armorPenRating + m_itemBonusStats.m_armorPenRating);
        }

        if (m_itemStats.m_hasteRating != 0 || m_itemBonusStats.m_hasteRating != 0)
        {
            l_string += " Hst +" + (m_itemStats.m_hasteRating + m_itemBonusStats.m_hasteRating);
        }

        return l_string;
    }

    // <editor-fold defaultstate="collapsed" desc="Getters/Setters">
    /**
     * @return the m_itemStats
     */

    public void setModified(boolean p_modified)
    {
        this.m_modified = p_modified;
    }

    public boolean isModified()
    {
        return this.m_modified;
    }
    
    /**
     * @return the m_weaponSpeed
     */
    public double getWeaponSpeed() {
        return m_weaponSpeed;
    }

    /**
     * @param m_weaponSpeed the m_weaponSpeed to set
     */
    public void setWeaponSpeed(double m_weaponSpeed) {
        this.m_weaponSpeed = m_weaponSpeed;
    }

    /**
     * @return the m_maxWeaponDamage
     */
    public double getMaxWeaponDamage() {
        return m_maxWeaponDamage;
    }

    /**
     * @param m_maxWeaponDamage the m_maxWeaponDamage to set
     */
    public void setMaxWeaponDamage(double m_maxWeaponDamage) {
        this.m_maxWeaponDamage = m_maxWeaponDamage;
    }

    /**
     * @return the m_minWeaponDamage
     */
    public double getMinWeaponDamage() {
        return m_minWeaponDamage;
    }

    /**
     * @param m_minWeaponDamage the m_minWeaponDamage to set
     */
    public void setMinWeaponDamage(double m_minWeaponDamage) {
        this.m_minWeaponDamage = m_minWeaponDamage;
    }

    public CStats getItemStats() {
        return m_itemStats;
    }

    /**
     * @param m_itemStats the m_itemStats to set
     */
    public void setItemStats(CStats m_itemStats) {
        this.m_itemStats = m_itemStats;
    }

    /**
     * @return the m_itemBonusStats
     */
    public CStats getItemBonusStats() {
        return m_itemBonusStats;
    }

    /**
     * @param m_itemBonusStats the m_itemBonusStats to set
     */
    public void setItemBonusStats(CStats m_itemBonusStats) {
        this.m_itemBonusStats = m_itemBonusStats;
    }

    /**
     * @return the m_htmlTooltip
     */
    public String getHtmlTooltip() {
        return m_htmlTooltip;
    }

    /**
     * @param m_htmlTooltip the m_htmlTooltip to set
     */
    public void setHtmlTooltip(String htmlTooltip) {
        this.m_htmlTooltip = htmlTooltip;
    }

    /**
     * @return the m_gemType
     */
    public GemType getGemType() {
        return m_gemType;
    }

    /**
     * @param m_gemType the m_gemType to set
     */
    public void setGemType(GemType m_gemType) {
        this.m_gemType = m_gemType;
    }
    
    /**
     * @return the m_itemType
     */
    public ItemType getItemType() {
        return m_itemType;
    }

    /**
     * @param m_itemType the m_itemType to set
     */
    public void setItemType(ItemType m_itemType) {
        this.m_itemType = m_itemType;
    }

    /**
     * @return the m_itemSlot
     */
    public ItemSlot getItemSlot() {
        return m_itemSlot;
    }

    /**
     * @param m_itemSlot the m_itemSlot to set
     */
    public void setItemSlot(ItemSlot m_itemSlot) {
        this.m_itemSlot = m_itemSlot;
    }

    /**
     * @return the m_id
     */
    public int getId() {
        return m_id;
    }

    /**
     * @param m_id the m_id to set
     */
    public void setId(int id) {
        this.m_id = id;
    }

    /**
     * @return the m_name
     */
    public String getName() {
        return m_name;
    }

    /**
     * @param m_name the m_name to set
     */
    public void setName(String name) {
        this.m_name = name;
    }

    /**
     * @return the m_itemQuality
     */
    public ItemQuality getGearQuality() {
        return m_itemQuality;
    }

    /**
     * @param m_itemQuality the m_itemQuality to set
     */
    public void setGearQuality(ItemQuality gearQuality) {
        this.m_itemQuality = gearQuality;
    }

    /**
     * @param m_itemQuality the m_itemQuality to set
     */
    public void setGearQuality(String gearQuality) {
        if (gearQuality != null)
        {
            this.m_itemQuality = convertGearQuality(gearQuality);
        }
    }

    /**
     * @return the m_iLevel
     */
    public int getILevel() {
        return m_iLevel;
    }

    /**
     * @param m_iLevel the m_iLevel to set
     */
    public void setILevel(int iLevel) {
        this.m_iLevel = iLevel;
    }

// </editor-fold>
    public void addSocketHolder(GemType p_gemType)
    {
        m_socketHolderList.add(new CSocketHolder(p_gemType));
    }

    public int getNumberOfSockets()
    {
        return this.m_socketHolderList.size();
    }

    public CSocketHolder getSocketHolder(int p_index)
    {
        return this.m_socketHolderList.get(p_index);
    }
    
    private ItemQuality convertGearQuality(String p_quality)
    {
        String l_lowerCase = p_quality.toLowerCase();

        if (l_lowerCase.equals("epic"))
        {
            return ItemQuality.EPIC;
        } else if (l_lowerCase.equals("legendary"))
        {
            return ItemQuality.LEGENDARY;
        } else if (l_lowerCase.equals("uncommon"))
        {
            return ItemQuality.UNCOMMON;
        } else if (l_lowerCase.equals("rare"))
        {
            return ItemQuality.RARE;
        }

        return ItemQuality.COMMON;
    }

    private String getGearQuality(ItemQuality p_gearQuality)
    {
        if (p_gearQuality == ItemQuality.EPIC)
        {
            return "Epic";
        } else if (p_gearQuality == ItemQuality.LEGENDARY)
        {
            return "Legendary";
        } else if (p_gearQuality == ItemQuality.UNCOMMON)
        {
            return "Uncommon";
        } else if (p_gearQuality == ItemQuality.RARE)
        {
            return "Rare";
        } 

        return "Common";
    }

    public void addXMLData(Element p_root)
    {
        // Add item id
        int l_nbrSockets = this.m_socketHolderList.size();
        Element l_item = p_root.addElement("item").
                        addAttribute("id", String.valueOf(this.getId())).
                        addAttribute("ilevel", String.valueOf(this.getILevel())).
                        addAttribute("quality", String.valueOf(this.getGearQuality())).
                        addAttribute("itemtype", String.valueOf(this.getItemType())).
                        addAttribute("itemslot", String.valueOf(this.getItemSlot())).
                        addAttribute("modified", CUtility.boolToString(this.isModified())).
                        addAttribute("gemtype", ((this.getGemType() == null) ? "NULL":String.valueOf(this.getGemType())));
        Element l_name = l_item.addElement("name").addCDATA(this.getName());
        Element l_tooltip = l_item.addElement("tooltip").addCDATA(this.getHtmlTooltip());
        Element l_stats = l_item.addElement("stats");
        this.getItemStats().addXMLData(l_stats);
        Element l_bonusStats = l_item.addElement("bonusstats");
        this.getItemBonusStats().addXMLData(l_bonusStats);
        if (this.getWeaponSpeed() > 0.0)
        {
            Element l_weaponStats = l_item.addElement("weaponstats").
                                addAttribute("speed", String.valueOf(this.getWeaponSpeed())).
                                addAttribute("max", String.valueOf(this.getMaxWeaponDamage())).
                                addAttribute("min", String.valueOf(this.getMinWeaponDamage()));
        }
        
        if (l_nbrSockets != 0)
        {
            Element l_sockets = l_item.addElement("socketholder");
            for (int i = 0; i < l_nbrSockets; i ++)
            {
                l_sockets.addElement("socket").
                            addAttribute("type", String.valueOf(this.m_socketHolderList.get(i).getSocketType()));

            }
        }
    }

    private void parseXMLElement(Element p_element)
    {
        // p_element has our item ptr in it.
        this.setId(Integer.parseInt(p_element.attributeValue("id")));
        this.setILevel(Integer.parseInt(p_element.attributeValue("ilevel")));
        this.setGearQuality(p_element.attributeValue("quality"));
        this.setItemType(CItemType.getItemType(p_element.attributeValue("itemtype")));
        this.setItemSlot(CItemSlot.getItemSlot(p_element.attributeValue("itemslot")));
        String l_modified = p_element.attributeValue("modified");
        if (l_modified != null && !l_modified.equals(""))
        {
            this.setModified(CUtility.stringToBool(l_modified));
        }

        String l_gemType = p_element.attributeValue("gemtype");
        if (!l_gemType.equals("NULL"))
        {
            this.setGemType(CGemType.getGemType(l_gemType));
        }

        this.setName(p_element.valueOf("name"));
        this.setHtmlTooltip(p_element.valueOf("tooltip"));

        Node l_node = p_element.selectSingleNode("stats");
        this.getItemStats().parseXML(l_node);
        l_node = p_element.selectSingleNode("bonusstats");
        this.getItemBonusStats().parseXML(l_node);

        l_node = p_element.selectSingleNode("weaponstats");
        if (l_node != null)
        {
            this.setWeaponSpeed(Double.parseDouble(l_node.valueOf("@speed")));
            this.setMinWeaponDamage(Double.parseDouble(l_node.valueOf("@min")));
            this.setMaxWeaponDamage(Double.parseDouble(l_node.valueOf("@max")));
        }

        l_node = p_element.selectSingleNode("socketholder");
        if (l_node != null)
        {
            List l_list = l_node.selectNodes( "socket" );
            for (Iterator l_iter = l_list.iterator(); l_iter.hasNext(); ) {
                Element l_element = (Element) l_iter.next();
                GemType l_socketGemType = CGemType.getGemType(l_element.valueOf("@type"));
                this.addSocketHolder(l_socketGemType);
            }
        }

        // showData();
    }

    public CStats getTotalStats()
    {
        CStats l_stats = new CStats();
        l_stats.add(this.m_itemStats);
        l_stats.add(this.m_itemBonusStats);
        return l_stats;
    }
}
